package video.com.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Aspect
@Component
public class FormatUrl {

    @Value("${file.path}")
    private String filePath;

    @Pointcut ( "@annotation(video.com.aspect.FormatFileURL)")
    public void formatFileURLs(){}

    @AfterReturning(value = "formatFileURLs()", returning = "result")
    public Object after(JoinPoint joinPoint , Object result){
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();

        FormatFileURL annotation = signature.getMethod().getAnnotation(FormatFileURL.class);

        if(annotation == null){
            return result;
        }

        String[] value = annotation.value();
        Class<?> type = annotation.type();
        if(type == Object.class){

            List<Object> list = new ArrayList<Object>(){{add(result);}};

          aspectChangeVal(value,list);
        } else{
            for(String str : value){
                try {
                    Field field = type.getDeclaredField(str);
                    field.setAccessible(true);
                    Object object = field.get(result);
                    if(object == null){
                        continue;
                    }

                    field.set(result, object.toString().substring(filePath.length()));
                } catch (Exception e) {
                    continue;
                }
            }

            List<Object> collect = Arrays.stream(type.getDeclaredFields()).filter(item -> {
                return item.getType() == Map.class || item.getType() == List.class;
            }).map(item -> {
                item.setAccessible(true);
                Object o = new Object();
                try {
                    o = item.get(result);
                } catch (IllegalAccessException e) {
                    return null;
                }
                return o;
            }).collect(Collectors.toList());

            aspectChangeVal(value,collect);
        }

        return result;
    }


    public void aspectChangeVal(String[] arr, List<Object> objects){
        for(Object obj : objects){
            if(obj instanceof Map){
                for(String str: arr){
                    if(((Map) obj).get(str) != null){
                        ((Map) obj).put(str,((Map) obj).get(str).toString().substring(filePath.length()));
                    }
                }
            } else if(obj instanceof List){
                for(String str: arr){
                    ((List)obj).forEach(item ->
                            {
                                if(item instanceof Map){
                                    if(((Map) item).get(str) != null){
                                        ((Map) item).put(str,((Map) item).get(str).toString().substring(filePath.length()));
                                    }
                                }else{
                                    try {
                                        Field field = item.getClass().getDeclaredField(str);
                                        field.setAccessible(true);
                                        Object object = field.get(item);

                                        if(object != null){
                                            field.set(item,field.get(item).toString().substring(filePath.length()));
                                        }

                                    } catch (Exception e) {
                                        log.error("FormatFileURL注解切面在执行时出现错误, result 的类型为List，Item类型为其他");
                                    }
                                }

                            }
                    );
                }
            }
        }
    }
}
